/*
 *  MainComponent.cpp
 *  mediTock
 *
 *  Created by tjmitche on 02/04/2009.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#include "MainComponent.h"

//////////////
//==============================================================================


//==============================================================================


//////////////


MainComponent::MainComponent ()
{
	// This is where the main component is created, so we initialise and
	// configure it according to our needs.
	
	// One thing that covers is creating any widgets and components we want to
	// display. Also, if any widgets will need responding to, we must hook them up
	// to their listeners here too (and it's likely that this class itself will be
	// the listener in question, providing we've inherited the appropriate class!)
	
	// Create and add the rest of your components here!
	// e.g.
	//myButton = new TextButton (T("my button"), T("Click me!"));
	//addAndMakeVisible (myButton);
	
	//
		
	timerDisplayLabel = new Label (T("TimeDisplay"), String::empty); 
	
	addAndMakeVisible (timerDisplayLabel); 
	timerDisplayLabel->setJustificationType(Justification::centred);	
	//timerDisplayLabel->setColour(Label::textColourId, Colours::blue.withAlpha(0.8f));
	
	addAndMakeVisible (startStopButton = new TextButton (String::empty,T("click here to start/stop the timer")));
	startStopButton->addButtonListener (this);
	startStopButton->setClickingTogglesState(true);
	startStopButton->setColour (TextButton::buttonColourId, Colours::white);
	startStopButton->setColour (TextButton::buttonOnColourId, Colours::transparentBlack);
	startStopButton->setConnectedEdges (Button::ConnectedOnRight | Button::ConnectedOnLeft | Button::ConnectedOnBottom);
	
	addAndMakeVisible (resetButton = new TextButton (String::empty,T("click here to reset the timer")));
	resetButton->addButtonListener (this);
	resetButton->setColour (TextButton::buttonColourId, Colours::white);
	resetButton->setColour (TextButton::buttonOnColourId, Colours::transparentBlack);
	resetButton->setConnectedEdges (Button::ConnectedOnRight | Button::ConnectedOnLeft | Button::ConnectedOnBottom);
	
	preferencesWindow = new PreferencesWindow();
	
	addKeyListener(this);
	
	
	//everything's ready, reset the timer:
	reset();
}

MainComponent::~MainComponent ()
{
	// Be sure to destroy any objects you've created using 'new' here. If your objects
	// are on the stack (i.e. they were created without pointers or the 'new' operator,
	// then they die automatically. If you've created them
	// manually on the heap (for example, if you've got a pointer and you've created a new
	// object for it) then it must be deleted.
	
	// However, juce has a nice neat function that will destroy all Components that have
	// been added to a Component...
	
	deleteAllChildren();   // This will remove all the contained components, and delete
	// the objects for you.
	
	deleteAndZero (preferencesWindow);
}

//==============================================================================
void MainComponent::resized ()
{
	// This is called whenever this component's size changes. We could respond
	// to this in a number of ways, but the most obvious thing to do is reposition
	// all our widgets, using their 'setBounds()' function.
	// It's nice to position them relative to the size of this Component. That means
	// making use of the 'getWidth()' and 'getHeight()' functions to determine where
	// to put them and how big they should be.

	timerDisplayLabel->setBounds (0,	0, getWidth(), getHeight()-10);
	timerDisplayLabel->setFont((getWidth() + getHeight())/6.0f);

	startStopButton->setBounds(0,0,getWidth(),(int)(getHeight()*0.9f));
	resetButton->setBounds(0,(int)(getHeight()*0.9f),getWidth(),(int)(getHeight()*0.1f));
}

void MainComponent::paint (Graphics& g)
{
	// This does any drawing required on this Component's face. You can simply
	// call functions on the provided Graphics object - although you may want to
	// make use of 'getWidth()' and 'getHeight()' (members of this Component) to
	// make sure you're drawing in the right place!
	
	unsigned int height = getHeight();
	unsigned int width = getWidth();
	
	if(preTimeKeeper.getRemaining() > 0)
	{
		g.setColour (Colours::grey.withAlpha(0.5f)); 
		float percent = (float)(preTimeKeeper.getRemaining()) / (float)(preTimeKeeper.getDuration());
		if(percent > 0.5)
		{
			unsigned int fillHeight = (unsigned int)(height*(1.0-percent));
			g.fillRect (0,0,width,fillHeight*2);
		}
		else
		{
			unsigned int fillHeight = (unsigned int)(height*percent);
			g.fillRect (0,height-fillHeight*2,width,fillHeight*2);
		}
	}
}

String MainComponent::formatTime(int64 tickTime)//this variable should be called centseconds
{
	String timeString;
	//get hours minutes seconds and centiseconds
	int64 centSec = tickTime % 10;
	tickTime = (int64)(tickTime * 0.1f);
	unsigned int seconds = tickTime % 60;
	tickTime = (int64)(tickTime * 0.01667f);
	unsigned int minutes = tickTime % 60;
	tickTime = (int64)(tickTime * 0.01667f);
	unsigned int hours = tickTime % 60;
	//format string
	unsigned int digit1 = (unsigned int)(hours * 0.1f);
	unsigned int digit2 = hours % 10;
	timeString << digit1 << digit2 << ":";
	digit1 = (unsigned int)(minutes * 0.1f);
	digit2 = minutes % 10;
	timeString << digit1 << digit2 << ":";
	digit1 = (unsigned int)(seconds * 0.1f);
	digit2 = seconds % 10;
	timeString << String(digit1) << String(digit2) << T(":") << String(centSec);
	
	return timeString;
}

void MainComponent::start()
{

	lastTime = Time::getHighResolutionTicks();
	startTimer (100);  // repaint every 1/10 of a second	
}

void MainComponent::stop()
{
	if(!preferencesWindow->isVisible())
		stopTimer();
}

void MainComponent::reset()
{
	timeKeeper.setDuration(Time::secondsToHighResolutionTicks(preferencesWindow->getTimeInSeconds()));	//seconds
	preTimeKeeper.setDuration(Time::secondsToHighResolutionTicks(preferencesWindow->getPreTimeInSeconds()));
	countInPercent = 0;		
	ding = true;
	timerDisplayLabel->setText(formatTime((int64)(Time::highResolutionTicksToSeconds(timeKeeper.getRemaining())*10)), false);
	repaint();
}

void MainComponent::timerCallback()
{
	if(startStopButton->getToggleState())
	{
		int64 tickTime = Time::getHighResolutionTicks();
		int64 elapsed = tickTime - lastTime;
		lastTime = tickTime;
		
		if(preTimeKeeper.getRemaining() > 0)
		{
			preTimeKeeper.subtratTime(elapsed);
			countInPercent = (int)(100* ((float)(preTimeKeeper.getRemaining()) / 
								   (float)(preTimeKeeper.getDuration())));
			repaint();
		}
		else if(timeKeeper.getRemaining() > 0)
		{
			if(ding)
			{
				preferencesWindow->startTransport();
				ding = false;	
			}
			countInPercent = 0;
			timeKeeper.subtratTime(elapsed);
			timerDisplayLabel->setText (formatTime((unsigned int)(Time::highResolutionTicksToSeconds(timeKeeper.getRemaining())*10)), false);
		}
		else
		{
			preferencesWindow->startTransport();
			if(startStopButton->getToggleState())
				startStopButton->triggerClick();
			reset();
		}
	}
	else //preferences window must be open
	{
		if(preferencesWindow->preferencesChanged())
		{
			reset();
		}
		if(!preferencesWindow->isVisible())//window has been closed so stop the timer
		{
			stopTimer();
		}
	}
	
	//else if(preferencesWindow->)
	
}

void MainComponent::buttonClicked (Button* button)
{
	if(button == startStopButton)
	{
		if(startStopButton->getToggleState())
		{
			start();
		}
		else
		{
			stop();
			if(preTimeKeeper.getRemaining() > 0)
				reset();//flag to play sample when countInExpires
		}
	}
	else if(button == resetButton)
	{
		if(startStopButton->getToggleState())
			startStopButton->triggerClick();
		reset();
	}
}

bool MainComponent::keyPressed (const KeyPress& key, Component* originatingComponent)
{
	if(!startStopButton->getToggleState())
	{	
		int keycode = key.getKeyCode();
		
		if(keycode == KeyPress::leftKey)
			preferencesWindow->setTimerInSeconds(preferencesWindow->getTimeInSeconds() - 60);
		else if(keycode == KeyPress::rightKey)
			preferencesWindow->setTimerInSeconds(preferencesWindow->getTimeInSeconds() + 60);
		else if(keycode == KeyPress::downKey)
			preferencesWindow->setTimerInSeconds(preferencesWindow->getTimeInSeconds() - 60*60);
		else if(keycode == KeyPress::upKey)
			preferencesWindow->setTimerInSeconds(preferencesWindow->getTimeInSeconds() + 60*60);
		else
			return false;		//any other key
		
		reset();
		return true;
	}
	return false;
}
 

//==============================================================================

void MainComponent::showPreferences(void)
{
	//make prefs visible
	if(startStopButton->getToggleState())
		startStopButton->triggerClick();
	
	preferencesWindow->centreAroundComponent (this, 420, 270);
	preferencesWindow->makeVisible (true);
	
	startTimer(100);//this is a bit messy - currently using the timer to keep the clock display in sync with the prefs
}


